home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Internet Strate…Tools for the Enterprise / Microsoft Internet Strategy & Tools for the Enterprise.iso / content / devel.tls / icp / vbsamp / voicec-d.exe / WAVESTRM.CLS < prev   
Text File  |  1996-03-20  |  46KB  |  807 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "WaveStream"
  6. Attribute VB_Creatable = True
  7. Attribute VB_Exposed = True
  8. Option Explicit
  9. '--------------------------------------------------------------
  10. ' Public Variable Declarations
  11. '--------------------------------------------------------------
  12. Public Recording As Boolean             ' Public Recording Status Indicator...
  13. Public RecDeviceFree As Boolean         ' Public Recording Device Status Indicator...
  14. Public Playing As Boolean               ' Public Recording Status Indicator...
  15. Public PlayDeviceFree As Boolean        ' Public Recording Device Status Indicator...
  16.  
  17. Public waveChunkSize As Long            ' size of wave data buffer
  18. Public waveCodec As Long                ' acm codec compression format
  19. Public TIMESLICE As Single              ' recording interval...
  20.  
  21. '--------------------------------------------------------------
  22. Private Const MINSTREAM = 1
  23. Private Const MAXSTREAM = 32
  24. Private CurRecPos(MINSTREAM To MAXSTREAM) As Long  ' Current Recording Buffer Position
  25. Private CurPlayPos(MINSTREAM To MAXSTREAM) As Long ' Current Playing Buffer Position
  26.  
  27. Private Type WaveData                   ' [Wave Stream Segment]
  28.     Data() As Byte                      ' Wave data byte array
  29. End Type
  30.  
  31. Private Type WaveArray                  ' [Wave Stream]
  32.     Waves(MAXBUFFERS) As WaveData       ' Array of WaveBuffers
  33. End Type
  34.  
  35. Private Type uArrayWaves                ' [Array of Wave Streams]
  36.     Stream(MINSTREAM To MAXSTREAM) As WaveArray ' Wave Buffer Array...
  37.     QueuePos(MAXSTREAM - MINSTREAM + 1) As Long ' Wave Buffer Queue Position
  38. End Type
  39.  
  40. Private PlayWaveBuffer As uArrayWaves    ' Array Of WaveBuffer Data Type
  41. '--------------------------------------------------------------
  42.  
  43. '--------------------------------------------------------------
  44. Public Sub InitACMCodec(fmtType As Long, Time_Slice As Single)
  45. '--------------------------------------------------------------
  46.     Dim waveFmt As WAVEFORMATEX                             ' Wave format type
  47. '--------------------------------------------------------------
  48.     waveCodec = fmtType                                     ' Save compression format to public variable
  49.     TIMESLICE = Time_Slice                                  ' Save recording interval to public variable
  50.     Call InitWaveFormat(waveFmt, waveCodec, TIMESLICE)      ' Get wave format info
  51.     waveChunkSize = waveFmt.nAvgBytesPerSec * TIMESLICE     ' Save wave buffer size to public variable
  52. '--------------------------------------------------------------
  53. End Sub
  54. '--------------------------------------------------------------
  55.  
  56. '--------------------------------------------------------------
  57. Public Function StreamInQueue() As Long
  58. ' Return current stream index in queue for playback
  59. '--------------------------------------------------------------
  60.     StreamInQueue = PlayWaveBuffer.QueuePos(MINSTREAM)
  61. '--------------------------------------------------------------
  62. End Function
  63. '--------------------------------------------------------------
  64.  
  65. '--------------------------------------------------------------
  66. Public Sub RemoveStreamFromQueue(StreamIdx As Integer)
  67. ' Removes A Stream From The Wave PlayBack Queue When PlayBack Is Done
  68. '--------------------------------------------------------------
  69.     Dim Idx As Integer                                      ' Queue Array Element Variable
  70. '--------------------------------------------------------------
  71.     For Idx = MINSTREAM To MAXSTREAM                        ' For Each Stream In The Queue
  72.         If (PlayWaveBuffer.QueuePos(Idx) = StreamIdx) Then  ' If Stream Found In Queue...
  73.             PlayWaveBuffer.QueuePos(Idx) = 0                ' Remove Stream From Queue
  74.         ElseIf (Idx > MINSTREAM) Then                       ' If Not The First Item In The Queue...
  75.             If (PlayWaveBuffer.QueuePos(Idx - 1) = 0) Then  ' If Previous Item Was Removed...
  76.                 If (PlayWaveBuffer.QueuePos(Idx) = 0) Then Exit For
  77.                 PlayWaveBuffer.QueuePos(Idx - 1) = PlayWaveBuffer.QueuePos(Idx) ' Move Stream Up To New Position
  78.                 PlayWaveBuffer.QueuePos(Idx) = 0            ' Remove Stream From Old Position
  79.             End If
  80.         End If
  81.     Next                                                    ' Next Stream In Queue
  82. '--------------------------------------------------------------
  83. End Sub
  84. '--------------------------------------------------------------
  85.  
  86. '--------------------------------------------------------------
  87. Public Sub WaitForCallBack(CallBackBit As Long, cbFlag As Long)
  88. ' Waits For Asynchronous Function Callback Bit To Be Set.
  89. '--------------------------------------------------------------
  90.     Do Until (((CallBackBit And cbFlag) = cbFlag) Or _
  91.                (CallBackBit = WHDR_PREPARED) Or _
  92.                (CallBackBit = 0))       ' Check For (CallBack Bit Or Null)...
  93.         DoEvents                        ' Post Events...
  94.     Loop
  95. '--------------------------------------------------------------
  96. End Sub
  97. '--------------------------------------------------------------
  98.  
  99. '--------------------------------------------------------------
  100. Public Sub WaitForACMCallBack(CallBackBit As Long, cbFlag As Long)
  101. ' Waits For Asynchronous Function Callback Bit To Be Set.
  102. '--------------------------------------------------------------
  103.     Do Until (((CallBackBit And cbFlag) = cbFlag) Or _
  104.                (CallBackBit = 0))       ' Check For (CallBack Bit Or Null)...
  105.         DoEvents                        ' Post Events...
  106.     Loop
  107. '--------------------------------------------------------------
  108. End Sub
  109. '--------------------------------------------------------------
  110.  
  111. '--------------------------------------------------------------
  112. Private Sub InitWaveHDR(WaveHeader As WAVEHDR, waveFmt As WAVEFORMATEX, BuffSize As Long)
  113. ' Initialize's An Input Wave Header's DataBuffer And Size Members...
  114. '--------------------------------------------------------------
  115.     Dim rc As Long                                      ' Function Return Code...
  116. '--------------------------------------------------------------
  117.     WaveHeader.hData = GlobalAlloc(GMEM_MOVEABLE Or GMEM_SHARE Or GMEM_ZEROINIT, BuffSize) ' Allocate Global Memory
  118.     WaveHeader.lpData = GlobalLock(WaveHeader.hData)    ' Lock Memory handle
  119.  
  120.     WaveHeader.dwBufferLength = BuffSize                ' Get Wave Buffer Size
  121.     WaveHeader.dwFlags = 0                              ' Must Be Set To 0 For (waveOutPrepareHeader & waveInPrepareHeader)
  122. '--------------------------------------------------------------
  123. End Sub
  124. '--------------------------------------------------------------
  125.  
  126. '--------------------------------------------------------------
  127. Private Function FreeWaveHDR(WaveHeader As WAVEHDR) As Boolean
  128. '--------------------------------------------------------------
  129.     Dim rc As Long                                      ' Function return code
  130. '--------------------------------------------------------------
  131.     rc = GlobalUnlock(WaveHeader.lpData)                ' Unlock Global Memory
  132.     rc = GlobalFree(WaveHeader.hData)                   ' Free Global Memory
  133.     
  134.     FreeWaveHDR = True                                  ' Set Default Return Code
  135. '--------------------------------------------------------------
  136. End Function
  137. '--------------------------------------------------------------
  138.  
  139. '--------------------------------------------------------------
  140. Private Sub InitAcmHDR(hAS As Long, acmHdr As ACMSTREAMHEADER, wavHdr As WAVEHDR)
  141. ' Initialize's An Input Wave Header's DataBuffer And Size Members...
  142. '--------------------------------------------------------------
  143.     Dim rc As Long                                      ' Function Return Code...
  144.     Dim OutBytes As Long
  145. '--------------------------------------------------------------
  146.     acmHdr.cbStruct = Len(acmHdr)                       ' Size of header in bytes
  147.     acmHdr.dwStatus = 0                                 ' Must be initialized to 0
  148.     acmHdr.dwUser = 0                                   ' clear user def info
  149.     acmHdr.cbSrcLengthUsed = 0                          ' Must be initialized to 0
  150.     acmHdr.cbDstLengthUsed = 0                          ' Must be initialized to 0
  151.     
  152.     acmHdr.pbSrc = wavHdr.lpData                        ' Copy address of unprocessed data
  153.     acmHdr.cbSrcLength = wavHdr.dwBufferLength          ' Copy size of unprocessed data
  154.     
  155.     rc = acmStreamSize(hAS, acmHdr.cbSrcLength, acmHdr.cbDstLength, ACM_STREAMSIZEF_SOURCE)
  156.     Call AudioErrorHandler(rc, "acmStreamSize")
  157.     
  158.     ' Allocate memory for de/compression
  159.     acmHdr.dwDstUser = GlobalAlloc(GMEM_MOVEABLE Or GMEM_SHARE Or GMEM_ZEROINIT, acmHdr.cbDstLength)                                     ' Allocate Global Memory
  160.     acmHdr.cbDst = GlobalLock(acmHdr.dwDstUser)         ' Lock Memory handle
  161. '--------------------------------------------------------------
  162. End Sub
  163. '--------------------------------------------------------------
  164.  
  165. '--------------------------------------------------------------
  166. Private Sub FreeAcmHdr(acmHdr As ACMSTREAMHEADER)
  167. ' Initialize's An Input Wave Header's DataBuffer And Size Members...
  168. '--------------------------------------------------------------
  169.     Dim rc As Long                                      ' Function Return Code...
  170. '--------------------------------------------------------------
  171.     rc = GlobalUnlock(acmHdr.cbDst)                     ' Unlock Global Memory
  172.     rc = GlobalFree(acmHdr.dwDstUser)                   ' Free Global Memory
  173. '--------------------------------------------------------------
  174. End Sub
  175. '--------------------------------------------------------------
  176.  
  177. '------------------------------------------------------------------
  178. Public Function RecordWave(hWND As Long, ByVal TCPSocket As Variant) As Boolean
  179. ' Records Audio Sounds To A String Buffer And Sends Buffer To TCP/IP Socket...
  180. '------------------------------------------------------------------
  181.     Dim rc As Long                                      ' Function Return Code
  182.     Dim hAS As Long                                     ' ACM stream device
  183.     Dim cWavefmt As WAVEFORMATEX                        ' Wave compression format
  184.     Dim acmHdr As ACMSTREAMHEADER                       ' ACM stream header
  185.     Dim acmHdr_x As ACMSTREAMHEADER                     ' <<Double Buffering>> ACM stream header
  186.     Dim hWaveIn As Long                                 ' Handle To An Input Wave Device
  187.     Dim waveFmt As WAVEFORMATEX                         ' Wave compression format
  188.     Dim WaveInHDR As WAVEHDR                            ' Handle To An Input Wave Device Header
  189.     Dim WaveInHDR_x As WAVEHDR                          ' <<Double Buffering>> Handle To An xtra Input Wave Device Header
  190. '------------------------------------------------------------------
  191.     RecDeviceFree = False                               ' Allocate Recording Device
  192.     
  193.     Do While Not PlayDeviceFree                         ' Wait For Play Device To Free
  194.         DoEvents                                        ' Yield Events...
  195.     Loop                                                ' Check Play Device Status
  196.     
  197.     Call InitWaveFormat(waveFmt, WAVE_FORMAT_PCM, TIMESLICE)   ' Set current wave format
  198.     
  199.     ' Open Input Wave Device, Let WAVE_MAPPER Pick The Best Device...
  200.     rc = waveInOpen(hWaveIn, WAVE_MAPPER, waveFmt, 0&, 0&, CALLBACK_NULL)
  201.     If Not AudioErrorHandler(rc, "WaveInOpen") Then Exit Function ' Validate Function Return Code
  202.     
  203.     '<<Double Buffering>> Initialize Wave Header Format Information
  204.     Call InitWaveHDR(WaveInHDR_x, waveFmt, (waveFmt.nAvgBytesPerSec * TIMESLICE))
  205.         
  206.     ' Initialize Wave Header Format Information
  207.     Call InitWaveHDR(WaveInHDR, waveFmt, (waveFmt.nAvgBytesPerSec * TIMESLICE))
  208.     
  209.     ' <<Double Buffering>> Prepare Input Wave Device Header
  210.     rc = waveInPrepareHeader(hWaveIn, WaveInHDR_x, Len(WaveInHDR_x)) ' Validate Return Code
  211.     If Not AudioErrorHandler(rc, "waveInPrepareHeader_x") Then GoTo ErrorRecordWave
  212.  
  213.     ' Prepare Input Wave Device Header
  214.     rc = waveInPrepareHeader(hWaveIn, WaveInHDR, Len(WaveInHDR)) ' Validate Return Code
  215.     If Not AudioErrorHandler(rc, "waveInPrepareHeader") Then GoTo ErrorRecordWave
  216.     
  217.     ' <<Double Buffering>> Wait For Wave (xtra)Header CallBack
  218.     Call WaitForCallBack(WaveInHDR_x.dwFlags, WHDR_PREPARED)
  219.     
  220.     ' Wait For Wave Header CallBack
  221.     Call WaitForCallBack(WaveInHDR.dwFlags, WHDR_PREPARED)
  222.     
  223.     ' <<Double Buffering>> Add Input Wave (xtra)Buffer To Wave Input Device
  224.     rc = waveInAddBuffer(hWaveIn, WaveInHDR_x, Len(WaveInHDR_x)) ' Validate Return Code
  225.     If Not AudioErrorHandler(rc, "waveInAddBuffer_x") Then GoTo ErrorRecordWave
  226.  
  227.     ' Add Input Wave Buffer To Wave Input Device
  228.     rc = waveInAddBuffer(hWaveIn, WaveInHDR, Len(WaveInHDR)) ' Validate Return Code
  229.     If Not AudioErrorHandler(rc, "waveInAddBuffer") Then GoTo ErrorRecordWave
  230.         
  231.     ' <<Double Buffering>> Wait For Wave (xtra)Header CallBack
  232.     Call WaitForCallBack(WaveInHDR_x.dwFlags, WHDR_PREPARED)
  233.     
  234.     ' Wait For Wave Header CallBack
  235.     Call WaitForCallBack(WaveInHDR.dwFlags, WHDR_PREPARED)
  236.     
  237.     Call InitWaveFormat(cWavefmt, waveCodec, TIMESLICE)   ' Set current wave format
  238.     
  239.     ' Open/Configure an acm Stream Handle For Compression
  240.     rc = acmStreamOpen(hAS, 0&, waveFmt, cWavefmt, 0&, 0&, 0&, ACM_STREAMOPENF_NONREALTIME)
  241.     Call AudioErrorHandler(rc, "acmStreamOpen")
  242.     
  243.     ' Initialize Audio Compression Manager Streaming Headers
  244.     Call InitAcmHDR(hAS, acmHdr, WaveInHDR)
  245.     Call InitAcmHDR(hAS, acmHdr_x, WaveInHDR_x)
  246.     
  247.     ' Prepare acm Stream Header
  248.     rc = acmStreamPrepareHeader(hAS, acmHdr, 0&)
  249.     Call AudioErrorHandler(rc, "acmStreamPrepareHeader")
  250.     
  251.     ' Prepare acm Stream Header
  252.     rc = acmStreamPrepareHeader(hAS, acmHdr_x, 0&)
  253.     Call AudioErrorHandler(rc, "acmStreamPrepareHeader_x")
  254.         
  255.     ' <<Double Buffering>> Wait For Wave (xtra)Header CallBack
  256.     Call WaitForACMCallBack(acmHdr_x.dwStatus, ACMSTREAMHEADER_STATUSF_PREPARED)
  257.     
  258.     ' Wait For Wave Header CallBack
  259.     Call WaitForACMCallBack(acmHdr.dwStatus, ACMSTREAMHEADER_STATUSF_PREPARED)
  260.     
  261.     ' Start Input Wave Device Recording...
  262.     rc = waveInStart(hWaveIn)                           ' Validate Return Code
  263.     If Not AudioErrorHandler(rc, "waveInStart") Then GoTo ErrorRecordWave
  264.     
  265.     Do
  266.         ' <<Double Buffering>> Wait For Wave (xtra)Header CallBack
  267.         Call WaitForCallBack(WaveInHDR_x.dwFlags, WHDR_DONE)
  268.     
  269.         ' <<Double Buffering>> Compress acm Stream Wave Buffer
  270.         rc = acmStreamConvert(hAS, acmHdr_x, ACM_STREAMCONVERTF_BLOCKALIGN)
  271.         If Not AudioErrorHandler(rc, "acmStreamConvert_x") Then GoTo ErrorRecordWave
  272.  
  273.         rc = SendSoundAll(TCPSocket, acmHdr_x)           ' <<Double Buffering>> Send Sound Buffer To TCPSocket
  274.         If Not Recording Then Exit Do                       ' Evaluate Recording Stop Flag
  275.         
  276.         ' <<Double Buffering>> Add Input Wave (xtra)Buffer To Wave Input Device
  277.         rc = waveInAddBuffer(hWaveIn, WaveInHDR_x, Len(WaveInHDR_x)) ' Validate Return Code
  278.         If Not AudioErrorHandler(rc, "waveInAddBuffer_x") Then GoTo ErrorRecordWave
  279.         
  280.         Call WaitForCallBack(WaveInHDR.dwFlags, WHDR_DONE)  ' Wait For Wave Header CallBack
  281.         
  282.         ' Convert/Compress acm Stream Wave Buffer
  283.         rc = acmStreamConvert(hAS, acmHdr, ACM_STREAMCONVERTF_BLOCKALIGN)
  284.         If Not AudioErrorHandler(rc, "acmStreamConvert") Then GoTo ErrorRecordWave
  285.         
  286.         rc = SendSoundAll(TCPSocket, acmHdr)           ' Send Sound Buffer To TCPSocket
  287.         If Not Recording Then Exit Do                       ' Evaluate Recording Stop Flag
  288.     
  289.         ' Add Input Wave Buffer To Wave Input Device
  290.         rc = waveInAddBuffer(hWaveIn, WaveInHDR, Len(WaveInHDR)) ' Validate Return Code
  291.         If Not AudioErrorHandler(rc, "waveInAddBuffer") Then GoTo ErrorRecordWave
  292.     Loop While Recording                                   ' Continue Recording...
  293.     
  294.     ' <<Double Buffering>> UnPrepare acm Stream Header
  295.     rc = acmStreamUnprepareHeader(hAS, acmHdr_x, 0&)
  296.     Call AudioErrorHandler(rc, "acmStreamUnprepareHeader_x")
  297.     
  298.     ' UnPrepare acm Stream Header
  299.     rc = acmStreamUnprepareHeader(hAS, acmHdr, 0&)
  300.     Call AudioErrorHandler(rc, "acmStreamUnprepareHeader")
  301.     
  302.     ' Free globally allocated and locked memory variables...
  303.     Call FreeAcmHdr(acmHdr_x)                           ' Free extra wave header memory
  304.     Call FreeAcmHdr(acmHdr)                             ' Free wave header memory
  305.     
  306.     ' Close acm Stream Handle
  307.     rc = acmStreamClose(hAS, 0&)
  308.     Call AudioErrorHandler(rc, "acmStreamClose")
  309.     
  310.     ' <<Double Buffering>> Wait For Wave (xtra)Header CallBack
  311.     Call WaitForCallBack(WaveInHDR_x.dwFlags, WHDR_DONE)
  312.     
  313.     ' Wait For Wave Header CallBack
  314.     Call WaitForCallBack(WaveInHDR.dwFlags, WHDR_DONE)
  315.     
  316.     ' Stop Input Wave Device
  317.     rc = waveInStop(hWaveIn)                            ' Validate Return Code
  318.     If Not AudioErrorHandler(rc, "waveInStop") Then GoTo ErrorRecordWave
  319.    
  320.    ' UnPrepare Input Wave Device Header
  321.     rc = waveInUnprepareHeader(hWaveIn, WaveInHDR, Len(WaveInHDR)) ' Validate Return Code
  322.     If Not AudioErrorHandler(rc, "waveInUnPrepareHeader") Then GoTo ErrorRecordWave
  323.    
  324.    ' <<Double Buffering>> UnPrepare Input Wave Device (xtra)Header
  325.     rc = waveInUnprepareHeader(hWaveIn, WaveInHDR_x, Len(WaveInHDR_x)) ' Validate Return Code
  326.     If Not AudioErrorHandler(rc, "waveInUnPrepareHeader_x") Then GoTo ErrorRecordWave
  327.     
  328.     ' Close Input Wave Device
  329.     rc = waveInClose(hWaveIn)                           ' Validate Return Code
  330.     If Not AudioErrorHandler(rc, "waveInClose") Then Exit Function
  331.     
  332.     ' Clean Up Memory Data...
  333.     rc = FreeWaveHDR(WaveInHDR)                         ' Free Wave Header Data
  334.     rc = FreeWaveHDR(WaveInHDR_x)                       ' Free Extra Wave Header Data
  335.     
  336.     RecordWave = True                                   ' Return Success
  337.     RecDeviceFree = True                                ' Free Recording Device
  338.     Exit Function                                       ' Exit
  339. '------------------------------------------------------------------
  340. ErrorRecordWave:                                        ' Clean Up Environment(Brute force no error handling)...
  341. '------------------------------------------------------------------
  342.     rc = acmStreamUnprepareHeader(hAS, acmHdr, 0&)      ' Attempt To UnPrepare acm Stream Header
  343.     rc = acmStreamUnprepareHeader(hAS, acmHdr_x, 0&)    ' Attempt To UnPrepare acm Stream (xtra)Header
  344.     Call FreeAcmHdr(acmHdr)                             ' Free wave header memory
  345.     Call FreeAcmHdr(acmHdr_x)                           ' Free extra wave header memory
  346.     rc = acmStreamClose(hAS, 0&)                        ' Attempt To Close acm Stream Handle
  347.     
  348.     rc = waveInStop(hWaveIn)                            ' Attempt To Stop WaveInput Device
  349.     rc = waveInReset(hWaveIn)                           ' Attempt To Reset WaveInput Device
  350.     rc = waveInUnprepareHeader(hWaveIn, WaveInHDR, Len(WaveInHDR)) ' Attempt To Unprepare WaveInput Header
  351.     rc = waveInUnprepareHeader(hWaveIn, WaveInHDR_x, Len(WaveInHDR_x)) ' Attempt To Unprepare WaveInput (xtra)Header
  352.     rc = waveInClose(hWaveIn)                           ' Attempt To Close Wave Input Device
  353.     rc = FreeWaveHDR(WaveInHDR)                         ' Free Wave Header Data
  354.     rc = FreeWaveHDR(WaveInHDR_x)                       ' Free Extra Wave Header Data
  355.     
  356.     RecDeviceFree = True                                ' Free Recording Device
  357.     Exit Function                                       ' Exit
  358. '------------------------------------------------------------------
  359. End Function
  360. '------------------------------------------------------------------
  361.  
  362. '------------------------------------------------------------------
  363. Public Function PlayWave(hWND As Long, StreamIdx As Integer) As Boolean
  364. ' Play's Back Audio Wave Data From String Buffers...
  365. '------------------------------------------------------------------
  366.     Dim rc As Long                                      ' Function Return Code
  367.     Dim hAS As Long                                     ' ACM stream device
  368.     Dim acmHdr As ACMSTREAMHEADER                       ' ACM stream header
  369.     Dim acmHdr_x As ACMSTREAMHEADER                     ' <<Double Buffering>> ACM stream header
  370.     Dim cWavefmt As WAVEFORMATEX                        ' Wave compression format
  371.     Dim waveFmt As WAVEFORMATEX                         ' Wave format type
  372.     Dim hWaveOut As Long                                ' Handle To A Wave Output Device
  373.     Dim WaveOutHdr As WAVEHDR                           ' Handle To A Wave Output Device Header
  374.     Dim WaveOutHdr_x As WAVEHDR                         ' Handle To A Wave Output Device Header
  375. '------------------------------------------------------------------
  376.     Call InitWaveFormat(waveFmt, waveCodec, TIMESLICE)   ' Set current wave format
  377.     
  378.     ' Open Output Wave Device
  379.     rc = waveOutOpen(hWaveOut, WAVE_MAPPER, waveFmt, 0&, 0&, CALLBACK_NULL)
  380.     If Not AudioErrorHandler(rc, "waveOutOpen") Then Exit Function ' Validate Return Code
  381.     
  382.     PlayDeviceFree = False                              ' Allocate Recording Device
  383.     
  384.     ' Init Extra Wave Header Format Information
  385.     Call InitWaveHDR(WaveOutHdr_x, waveFmt, (waveFmt.nAvgBytesPerSec * TIMESLICE))
  386.         
  387.     ' Init Wave Header Format Information
  388.     Call InitWaveHDR(WaveOutHdr, waveFmt, (waveFmt.nAvgBytesPerSec * TIMESLICE))
  389.         
  390.     ' Prepare Output Wave Device Header
  391.     rc = waveOutPrepareHeader(hWaveOut, WaveOutHdr_x, Len(WaveOutHdr_x)) ' Validate Return Code
  392.     If Not AudioErrorHandler(rc, "waveOutPrepareHeader") Then GoTo ErrorPlayWave
  393.     
  394.     ' Prepare Output Wave Device Header
  395.     rc = waveOutPrepareHeader(hWaveOut, WaveOutHdr, Len(WaveOutHdr)) ' Validate Return Code
  396.     If Not AudioErrorHandler(rc, "waveOutPrepareHeader") Then GoTo ErrorPlayWave
  397.     
  398.     ' <<<Double Buffer>>> Copy (extra)Wave Data To Buffer
  399.     If Not (LoadPlayBuffer(hWaveOut, WaveOutHdr_x, waveFmt, _
  400.                            PlayWaveBuffer.Stream(StreamIdx).Waves(CurPlayPos(StreamIdx)).Data, _
  401.                            CurPlayPos(StreamIdx))) Then GoTo ErrorPlayWave ' Cleanup And Leave
  402.     
  403.     ' <<Double Buffering>> Wait For Wave (xtra)Header CallBack
  404.     Call WaitForCallBack(WaveOutHdr_x.dwFlags, WHDR_PREPARED)
  405.     
  406.     ' Wait For Wave Header CallBack
  407.     Call WaitForCallBack(WaveOutHdr.dwFlags, WHDR_PREPARED)
  408.     
  409.     'Call InitWaveFormat(cWavefmt, waveCodec, TIMESLICE)   ' Set current wave format
  410.     Call InitWaveFormat(cWavefmt, WAVE_FORMAT_PCM, TIMESLICE)   ' Set current wave format
  411.     
  412.     ' Open/Configure an acm Stream Handle For Compression
  413.     rc = acmStreamOpen(hAS, 0&, waveFmt, cWavefmt, 0&, 0&, 0&, ACM_STREAMOPENF_NONREALTIME)
  414.     Call AudioErrorHandler(rc, "acmStreamOpen")
  415.     
  416.     ' Initialize Audio Compression wave streaming headers...
  417.     Call InitAcmHDR(hAS, acmHdr, WaveOutHdr)
  418.     Call InitAcmHDR(hAS, acmHdr_x, WaveOutHdr_x)
  419.     
  420.     ' Prepare acm Stream Header
  421.     rc = acmStreamPrepareHeader(hAS, acmHdr, 0&)
  422.     Call AudioErrorHandler(rc, "acmStreamPrepareHeader")
  423.     
  424.     ' Prepare acm Stream Header
  425.     rc = acmStreamPrepareHeader(hAS, acmHdr_x, 0&)
  426.     Call AudioErrorHandler(rc, "acmStreamPrepareHeader_x")
  427.         
  428.     ' <<Double Buffering>> Wait For Wave (xtra)Header CallBack
  429.     Call WaitForACMCallBack(acmHdr_x.dwStatus, ACMSTREAMHEADER_STATUSF_PREPARED)
  430.     
  431.     ' Wait For Wave Header CallBack
  432.     Call WaitForACMCallBack(acmHdr.dwStatus, ACMSTREAMHEADER_STATUSF_PREPARED)
  433.     
  434.     ' <<<Double Buffer>>> Write (extra)Wave Buffer To Output Device...
  435.     rc = waveOutWrite(hWaveOut, WaveOutHdr_x, Len(WaveOutHdr_x))
  436.     If Not AudioErrorHandler(rc, "waveOutWrite_x") Then GoTo ErrorPlayWave ' Validate Return Code
  437.  
  438.     Do
  439.         ' Copy Wave Data To Buffer
  440.         If Not (LoadPlayBuffer(hWaveOut, WaveOutHdr, waveFmt, _
  441.                                PlayWaveBuffer.Stream(StreamIdx).Waves(CurPlayPos(StreamIdx)).Data, _
  442.                                CurPlayPos(StreamIdx))) Then GoTo CleanUpPlayWave ' Cleanup And Leave
  443.  
  444.         ' <<Double Buffering>> Compress acm Stream Wave Buffer
  445.         rc = acmStreamConvert(hAS, acmHdr, ACM_STREAMCONVERTF_BLOCKALIGN)
  446.         If Not AudioErrorHandler(rc, "acmStreamConvert") Then GoTo ErrorPlayWave
  447.         
  448.         ' Write Wave Buffer To Output Device...
  449.         rc = waveOutWrite(hWaveOut, WaveOutHdr, Len(WaveOutHdr))
  450.         If Not AudioErrorHandler(rc, "waveOutWrite") Then GoTo ErrorPlayWave ' Validate Return Code
  451.             
  452.         ' <<<Double Buffer>>> Wait For Wave Header CallBack
  453.         Call WaitForCallBack(WaveOutHdr_x.dwFlags, WHDR_DONE)
  454.         
  455.         ' <<<Double Buffer>>> Copy (extra)Wave Data To Buffer
  456.         If Not (LoadPlayBuffer(hWaveOut, WaveOutHdr_x, waveFmt, _
  457.                                PlayWaveBuffer.Stream(StreamIdx).Waves(CurPlayPos(StreamIdx)).Data, _
  458.                                CurPlayPos(StreamIdx))) Then GoTo CleanUpPlayWave ' Cleanup And Leave
  459.  
  460.         ' <<Double Buffering>> Compress acm Stream Wave Buffer
  461.         rc = acmStreamConvert(hAS, acmHdr_x, ACM_STREAMCONVERTF_BLOCKALIGN)
  462.         If Not AudioErrorHandler(rc, "acmStreamConvert_x") Then GoTo ErrorPlayWave
  463.         
  464.         ' <<<Double Buffer>>> Write (extra)Wave Buffer To Output Device...
  465.         rc = waveOutWrite(hWaveOut, WaveOutHdr_x, Len(WaveOutHdr_x))
  466.         If Not AudioErrorHandler(rc, "waveOutWrite_x") Then GoTo ErrorPlayWave ' Validate Return Code
  467.         
  468.         ' Wait For Wave Header CallBack
  469.         Call WaitForCallBack(WaveOutHdr.dwFlags, WHDR_DONE)
  470.     Loop While Playing                                    ' Continue Playing...
  471.     
  472. '------------------------------------------------------------------
  473. CleanUpPlayWave:                                          ' Cleanup...
  474. '------------------------------------------------------------------
  475.     ' <<Double Buffering>> UnPrepare acm Stream Header
  476.     rc = acmStreamUnprepareHeader(hAS, acmHdr_x, 0&)
  477.     Call AudioErrorHandler(rc, "acmStreamUnprepareHeader_x")
  478.     
  479.     ' UnPrepare acm Stream Header
  480.     rc = acmStreamUnprepareHeader(hAS, acmHdr, 0&)
  481.     Call AudioErrorHandler(rc, "acmStreamUnprepareHeader")
  482.     
  483.     Call FreeAcmHdr(acmHdr)                             ' Free wave header memory
  484.     Call FreeAcmHdr(acmHdr_x)                           ' Free extra wave header memory
  485.     
  486.     ' Close acm Stream Handle
  487.     rc = acmStreamClose(hAS, 0&)
  488.     Call AudioErrorHandler(rc, "acmStreamClose")
  489.     
  490.     ' Wait For Wave Header CallBack
  491.     Call WaitForCallBack(WaveOutHdr.dwFlags, WHDR_DONE)
  492.     
  493.     ' Unprepare Wave Output Buffer
  494.     rc = waveOutUnprepareHeader(hWaveOut, WaveOutHdr, Len(WaveOutHdr))
  495.     
  496.     ' <<Double Buffer>> Wait For Wave Header CallBack
  497.     Call WaitForCallBack(WaveOutHdr_x.dwFlags, WHDR_DONE)
  498.     
  499.     ' <<Double Buffer>> Unprepare Wave Output Buffer
  500.     rc = waveOutUnprepareHeader(hWaveOut, WaveOutHdr_x, Len(WaveOutHdr_x))
  501.  
  502.     ' Close Output Wave Device
  503.     rc = waveOutClose(hWaveOut)
  504.     If Not AudioErrorHandler(rc, "waveOutClose") Then Exit Function ' Validate Return Code
  505.     
  506.     ' Clean Up Memory Data...
  507.     rc = FreeWaveHDR(WaveOutHdr)                        ' Free Wave Header Data
  508.     rc = FreeWaveHDR(WaveOutHdr_x)                      ' Free Extra Wave Header Data
  509.     
  510.     PlayWave = True                                     ' Return Success
  511.     PlayDeviceFree = True                               ' Free Recording Device
  512.     Exit Function                                       ' Exit
  513. '------------------------------------------------------------------
  514. ErrorPlayWave:                                          ' Handle Errors And Cleanup...
  515. '------------------------------------------------------------------
  516.     rc = acmStreamUnprepareHeader(hAS, acmHdr, 0&)      ' Attempt To UnPrepare acm Stream Header
  517.     rc = acmStreamUnprepareHeader(hAS, acmHdr_x, 0&)    ' Attempt To UnPrepare acm Stream (xtra)Header
  518.     Call FreeAcmHdr(acmHdr)                             ' Free wave header memory
  519.     Call FreeAcmHdr(acmHdr_x)                           ' Free extra wave header memory
  520.     rc = acmStreamClose(hAS, 0&)                        ' Attempt To Close acm Stream Handle
  521.     
  522.     rc = waveOutUnprepareHeader(hWaveOut, WaveOutHdr, Len(WaveOutHdr)) ' Attempt To Unprepare Header
  523.     rc = waveOutUnprepareHeader(hWaveOut, WaveOutHdr_x, Len(WaveOutHdr_x)) ' Attempt To Unprepare Header
  524.     rc = waveOutClose(hWaveOut)                         ' Close Wave Output Device
  525.     rc = FreeWaveHDR(WaveOutHdr)                        ' Free Wave Header Data
  526.     rc = FreeWaveHDR(WaveOutHdr_x)                      ' Free Extra Wave Header Data
  527.     
  528.     PlayDeviceFree = True                               ' Free Recording Device Flag
  529.     Exit Function                                       ' Exit
  530. '------------------------------------------------------------------
  531. End Function
  532. '------------------------------------------------------------------
  533.  
  534. '------------------------------------------------------------------
  535. Private Sub IncBufferPointer(NextVal As Long)
  536. ' Moves Buffer Pointer Up One Notch In A Continuous Loop...
  537. '------------------------------------------------------------------
  538.     If NextVal < MAXBUFFERS Then        ' If Not At End Of Buffer
  539.         NextVal = NextVal + 1           ' Increment Buffer Pointer
  540.     Else                                ' At End Of Buffer
  541.         NextVal = MINBUFFERS            ' Go To Beginning Of Buffer
  542.     End If
  543. '------------------------------------------------------------------
  544. End Sub
  545. '------------------------------------------------------------------
  546.  
  547. '------------------------------------------------------------------
  548. Private Sub InitWaveFormat(waveFmt As WAVEFORMATEX, fmtType As Long, Time_Slice As Single)
  549. ' Initializes Wave Format Data Type
  550. '------------------------------------------------------------------
  551.     Dim i As Long
  552. '------------------------------------------------------------------
  553.     Select Case fmtType
  554.     Case WAVE_FORMAT_ADPCM
  555.         waveFmt.wFormatTag = WAVE_FORMAT_ADPCM          ' wave format type
  556.         waveFmt.nChannels = 1                           ' number of channels - mono
  557.         waveFmt.wBitsPerSample = 4                      ' bits/sample of TRUESPEECH - not used.
  558.         waveFmt.nSamplesPerSec = c8_0kHz                ' sample rate kHz
  559.         waveFmt.nAvgBytesPerSec = 4055                  ' Bytes/Sec
  560.         waveFmt.nBlockAlign = 256                       ' block size of data
  561.         waveFmt.cbSize = 2                              ' extra bytes used for WaveFormatEx
  562.         waveFmt.xBytes(0) = &HF9                        ' Fact Chunk - Byte 0
  563.         waveFmt.xBytes(1) = &H1                         ' Fact Chunk - Byte 1
  564.     Case WAVE_FORMAT_MSN_AUDIO          ' Initialize Wave Format - WAVE_FORMAT_MSN_AUDIO
  565.         waveFmt.wFormatTag = WAVE_FORMAT_MSN_AUDIO      ' wave format type
  566.         waveFmt.nChannels = 1                           ' number of channels - mono
  567.         waveFmt.wBitsPerSample = 0                      ' bits/sample of TRUESPEECH - not used.
  568.         waveFmt.cbSize = 4                              ' extra bytes used for WaveFormatEx
  569.         waveFmt.xBytes(0) = &H40                        ' Fact Chunk - Byte 0
  570.         waveFmt.xBytes(1) = &H1                         ' Fact Chunk - Byte 1
  571. '<<< 8.0 kHz - 8200 Bauds >>>  (Fair, No FeedBack)
  572.         waveFmt.nSamplesPerSec = c8_0kHz                ' sample rate kHz
  573.         waveFmt.nAvgBytesPerSec = 1025                  ' Bytes/Sec
  574.         waveFmt.nBlockAlign = 41                        ' block size of data
  575.         waveFmt.xBytes(2) = &H8                         ' Fact Chunk - Byte 2
  576.         waveFmt.xBytes(3) = &H20                        ' Fact Chunk - Byte 3
  577. '<<< 8.0 kHz - 10000 Bauds >>> (Excellent, No FeedBack)
  578. '        WaveFmt.nSamplesPerSec = c8_0kHz                ' sample rate kHz
  579. '        WaveFmt.nAvgBytesPerSec = 1250                  ' Bytes/Sec
  580. '        WaveFmt.nBlockAlign = 50                        ' block size of data
  581. '        WaveFmt.xBytes(2) = &H10                        ' Fact Chunk - Byte 2
  582. '        WaveFmt.xBytes(3) = &H27                        ' Fact Chunk - Byte 3
  583. '<<< 11.025 kHz - 11301 Bauds >>> (Bad, FeedBack)
  584. '<<< 11.025 kHz - 12128 Bauds >>> (Bad, FeedBack)
  585. '<<< 11.025 kHz - 13782 Bauds >>> (Bad, FeedBack)
  586.     Case WAVE_FORMAT_GSM610             ' Initialize Wave Format - WAVE_FORMAT_GSM610
  587.         waveFmt.wFormatTag = WAVE_FORMAT_GSM610         ' wave format type
  588.         waveFmt.nChannels = 1                           ' number of channels - mono
  589.         waveFmt.nSamplesPerSec = c8_0kHz                ' sample rate kHz
  590.         waveFmt.nAvgBytesPerSec = 1625                  ' Bytes/Sec
  591.         waveFmt.nBlockAlign = 65                        ' block size of data
  592.         waveFmt.wBitsPerSample = 0                      ' bits/sample of TRUESPEECH - not used.
  593.         waveFmt.cbSize = 2                              ' extra bytes used for WaveFormatEx
  594.         waveFmt.xBytes(0) = &H40                        ' Fact Chunk - Byte 0
  595.         waveFmt.xBytes(1) = &H1                         ' Fact Chunk - Byte 1
  596.     Case WAVE_FORMAT_PCM                ' Initialize Wave Format - WAVE_FORMAT_PCM
  597.         waveFmt.wFormatTag = WAVE_FORMAT_PCM                ' format type
  598.         waveFmt.nChannels = WAVE_FORMAT_1M08                ' number of channels (i.e. mono, stereo, etc.)
  599.         waveFmt.nSamplesPerSec = c8_0kHz                    ' sample rate 8.0 kHz
  600.         waveFmt.nAvgBytesPerSec = waveFmt.nSamplesPerSec    ' for buffer estimation
  601.         waveFmt.wBitsPerSample = 8                          ' [8, 16, or 0]
  602.         waveFmt.nBlockAlign = waveFmt.nChannels * waveFmt.wBitsPerSample / 8 '  block size of data
  603.         waveFmt.cbSize = 0                                  ' Not Used If [wFormatTag= WAVE_FORMAT_PCM]
  604.     End Select
  605. '------------------------------------------------------------------
  606. End Sub
  607. '------------------------------------------------------------------
  608.  
  609. '--------------------------------------------------------------
  610. Public Function AddStreamToQueue(StreamIdx As Integer)
  611. ' Puts An Incoming Wave Segment Into The Wave PlayBack Queue
  612. '--------------------------------------------------------------
  613.     Dim Idx As Integer                                  ' Queue Array Processing Variable
  614. '--------------------------------------------------------------
  615.     For Idx = MINSTREAM To MAXSTREAM                    ' For Each Stream In The Queue
  616.         If (PlayWaveBuffer.QueuePos(Idx) = StreamIdx) Then ' If Stream Already In Playback Queue
  617.             AddStreamToQueue = True                     ' Return Success
  618.             Exit Function                               ' Exit
  619.         ElseIf (PlayWaveBuffer.QueuePos(Idx) = 0) Then  ' If Queue Space Available...
  620.             PlayWaveBuffer.QueuePos(Idx) = StreamIdx    ' Put Stream Into The Playback Queue
  621.             AddStreamToQueue = True                     ' Return Success
  622.             Exit Function                               ' Exit
  623.         End If
  624.     Next                                                ' Next Stream In The Queue
  625. '--------------------------------------------------------------
  626. End Function
  627. '--------------------------------------------------------------
  628.  
  629. '------------------------------------------------------------------
  630. Public Sub SaveStreamBuffer(StreamIdx As Integer, recBuffer() As Byte)
  631. ' Saves A Record Buffer To A Record Buffer Array
  632. '------------------------------------------------------------------
  633.     ' If Buffer Is Free
  634.     If (LenB(MidB(PlayWaveBuffer.Stream(StreamIdx).Waves(CurRecPos(StreamIdx)).Data, 1)) < 3) Then
  635.         PlayWaveBuffer.Stream(StreamIdx).Waves(CurRecPos(StreamIdx)).Data = recBuffer ' Copy Buffer From Rec
  636.         Call IncBufferPointer(CurRecPos(StreamIdx)) ' Increment Buffer Pointer To Next Free Position...
  637.     End If                                          ' Else Ignore Buffer Data
  638. '------------------------------------------------------------------
  639. End Sub
  640. '------------------------------------------------------------------
  641.  
  642. '------------------------------------------------------------------
  643. Private Function LoadPlayBuffer(hWaveOut As Long, WaveOutHdr As WAVEHDR, waveFmt As WAVEFORMATEX, Data() As Byte, playBuffPos As Long) As Boolean
  644. ' Loads Audio Sound From A String Buffer Into A Wave Header Structure For PlayBack
  645. '------------------------------------------------------------------
  646.     Dim rc As Long                                  ' Return Code Variable
  647. '------------------------------------------------------------------
  648.     If (LenB(MidB(Data, 1)) > 2) Then
  649.         WaveOutHdr.dwBufferLength = UBound(Data) - LBound(Data) + 1 ' Get Wave Buffer Size
  650.         Call CopyBYTEStoPTR(WaveOutHdr.lpData, Data(0), _
  651.                             WaveOutHdr.dwBufferLength)  ' Copy Buffer From String To Pointer
  652.         Data = ""                                       ' Clear Buffer Space
  653.         Call IncBufferPointer(playBuffPos)              ' Increment Play Buffer ptr To Next Position...
  654.         
  655.         LoadPlayBuffer = True                           ' Return Success
  656.     End If
  657. '------------------------------------------------------------------
  658. End Function
  659. '------------------------------------------------------------------
  660.  
  661. '------------------------------------------------------------------
  662. Private Function SendSoundAll(Sockets As Variant, WaveHeader As ACMSTREAMHEADER) As Long
  663. ' Sends Sound Buffers To Each Valid Connection In A Connection Array
  664. '------------------------------------------------------------------
  665.     Dim Idx As Integer                              ' Socket cntl index
  666.     Dim rc As Long                                  ' Function Return Code
  667.     Dim Socket As Variant                           ' TCP socket control
  668. '------------------------------------------------------------------
  669.     For Each Socket In Sockets                      ' Check each socket
  670.         If (Socket.State = sckConnected) Then       ' If Connection Is Active
  671.             rc = SendSound(Socket, WaveHeader)      ' Send Sound To Socket Connection
  672.         End If
  673.     Next                                            ' Try Next LocalPort
  674. '------------------------------------------------------------------
  675. End Function
  676. '------------------------------------------------------------------
  677.  
  678. '------------------------------------------------------------------
  679. Private Function SendSound(Socket As Variant, acmHdr As ACMSTREAMHEADER) As Long
  680. ' Checks A Socket SendFlag Status, And Sends A WaveBuffer When Socket Is Ready
  681. '------------------------------------------------------------------
  682.     Dim WaveBuffer() As Byte                        ' Wave Buffer byte array
  683. '------------------------------------------------------------------
  684.     ReDim WaveBuffer(acmHdr.cbDstLengthUsed - 1) As Byte ' Allocate byte array
  685.     Call CopyPTRtoBYTES(WaveBuffer(0), acmHdr.cbDst, _
  686.                         acmHdr.cbDstLengthUsed)     ' Copy Data
  687.     Call Socket.SendData(WaveBuffer)                ' Send wave data into the socket
  688. '------------------------------------------------------------------
  689. End Function
  690. '------------------------------------------------------------------
  691.  
  692. '------------------------------------------------------------------
  693. Public Function AudioErrorHandler(rc As Long, fcnName As String) As Boolean
  694. '------------------------------------------------------------------
  695.     Dim msg As String               ' Error Message Body
  696. '------------------------------------------------------------------
  697.     AudioErrorHandler = False       ' Return Failure
  698.     
  699.     Select Case rc Or Err.LastDllError
  700. '   Select Case rc
  701.     Case MMSYSERR_NOERROR           ' no error
  702.         AudioErrorHandler = True    ' Return Success
  703.         Exit Function               ' Exit Function
  704.     Case MMSYSERR_ERROR             ' unspecified error
  705.         msg = "Unspecified Error."
  706.     Case MMSYSERR_BADDEVICEID       ' device ID out of range
  707.         msg = "device ID out of range"
  708.     Case MMSYSERR_NOTENABLED        ' driver failed enable
  709.         msg = "driver failed enable"
  710.     Case MMSYSERR_ALLOCATED         ' device already allocated
  711.         msg = "device already allocated"
  712.     Case MMSYSERR_INVALHANDLE       ' device handle is invalid
  713.         msg = "device handle is invalid"
  714.     Case MMSYSERR_NODRIVER          ' no device driver present
  715.         msg = "no device driver present"
  716.     Case MMSYSERR_NOMEM             ' memory allocation error
  717.         msg = "memory allocation error"
  718.     Case MMSYSERR_NOTSUPPORTED      ' function isn't supported
  719.         msg = "function isn't supported"
  720.     Case MMSYSERR_BADERRNUM         ' error value out of range
  721.         msg = "error value out of range"
  722.     Case MMSYSERR_INVALFLAG         ' invalid flag passed
  723.         msg = "invalid flag passed"
  724.     Case MMSYSERR_INVALPARAM        ' invalid parameter passed
  725.         msg = "invalid parameter passed"
  726.     Case MMSYSERR_LASTERROR         ' last error in range
  727.         msg = "last error in range"
  728.     Case WAVERR_BADFORMAT           ' unsupported wave format
  729.         msg = "unsupported wave format"
  730.     Case WAVERR_STILLPLAYING        ' still something playing
  731.         msg = "still something playing"
  732.     Case WAVERR_UNPREPARED          ' header not prepared
  733.         msg = "header not prepared"
  734.     Case WAVERR_LASTERROR           ' last error in range
  735.         msg = "last error in range"
  736.     Case WAVERR_SYNC                ' device is synchronous
  737.         msg = "device is synchronous"
  738.     Case ACMERR_NOTPOSSIBLE         ' The requested operation cannot be performed
  739.         msg = "The requested operation cannot be performed"
  740.     Case ACMERR_BUSY                ' The stream header specified is currently in use and cannot be unprepared
  741.         msg = "The acm stream header busy"
  742.     Case ACMERR_UNPREPARED
  743.         msg = "The acm stream header is not prepared"
  744.     Case ACMERR_CANCELED
  745.         msg = "The acm operation has been canceled"
  746.     Case ERROR_SHARING_VIOLATION    ' The process cannot access the file because it is being used by another process.
  747.         msg = "The process cannot access the file because it is being used by another process."
  748.     Case Else                       ' Unknown MM Error!
  749.         msg = "Unknown MM Error!"
  750.     End Select
  751.     
  752.     ' Format Text Body Of Message
  753.     msg = "Error In " & fcnName & _
  754.           " rc= " & Str$(rc) & _
  755.           " MSG= " & msg & _
  756.           " LastDllError= " & Hex(Err.LastDllError) & _
  757.           " Source= " & Err.Source & vbCrLf
  758.     
  759.     Debug.Print msg                 ' Print Error Message
  760.     MsgBox msg
  761.     Exit Function                   ' Exit
  762. '------------------------------------------------------------------
  763. End Function
  764. '------------------------------------------------------------------
  765.  
  766. '------------------------------------------------------------------
  767. Private Sub Class_Initialize()
  768. '------------------------------------------------------------------
  769.     Recording = False                                   ' Set Recording Status Off...
  770.     Playing = False                                     ' Set Playing Status Off...
  771.     RecDeviceFree = True                                ' Set Rec Device Free Status Indicator TRUE
  772.     PlayDeviceFree = True                               ' Set Play Device Free Status Indicator TRUE
  773.     Call InitACMCodec(WAVE_FORMAT_PCM, 0.2)             ' Initialise codec default values...
  774. '------------------------------------------------------------------
  775. End Sub
  776. '------------------------------------------------------------------
  777.  
  778. '------------------------------------------------------------------
  779. Private Sub Class_Terminate()
  780. '------------------------------------------------------------------
  781.     Recording = False                                   ' Set Recording Status Off...
  782.     Playing = False                                     ' Set Playing Status Off...
  783.     RecDeviceFree = False                               ' Set Rec Device Free Status Indicator TRUE
  784.     PlayDeviceFree = False                              ' Set Play Device Free Status Indicator TRUE
  785. '------------------------------------------------------------------
  786. End Sub
  787. '------------------------------------------------------------------
  788.  
  789. '------------------------------------------------------------------
  790. Private Sub debugACM(acmHdr As ACMSTREAMHEADER)
  791. '------------------------------------------------------------------
  792.     ' Used for debugging the audio compression streaming
  793.     MsgBox "cbStruct:" & CStr(acmHdr.cbStruct) & vbCrLf & "dwStatus:" & CStr(acmHdr.dwStatus) & vbCrLf & _
  794.            "dwUser:" & CStr(acmHdr.dwUser) & vbCrLf & _
  795.            "pbSrc:" & CStr(acmHdr.pbSrc) & vbCrLf & _
  796.            "cbSrcLength:" & CStr(acmHdr.cbSrcLength) & vbCrLf & _
  797.            "cbSrcLengthUsed:" & CStr(acmHdr.cbSrcLengthUsed) & vbCrLf & _
  798.            "dwSrcUser:" & CStr(acmHdr.dwSrcUser) & vbCrLf & _
  799.            "cbDst:" & CStr(acmHdr.cbDst) & vbCrLf & _
  800.            "cbDstLength:" & CStr(acmHdr.cbDstLength) & vbCrLf & _
  801.            "cbDstLengthUsed:" & CStr(acmHdr.cbDstLengthUsed) & vbCrLf & _
  802.            "dwDstUser:" & CStr(acmHdr.dwDstUser)
  803. '------------------------------------------------------------------
  804. End Sub
  805. '------------------------------------------------------------------
  806.  
  807.